研究笔记 | 基于OSMnx的全球路网数据获取与分析
摘要:OpenStreetMap数据是较为常用的开源数据,但其数据存在节点过多,拓扑结构差等问题。OSMnx基于OSM数据,对道路的拓扑结构进行了优化,添加了统计和分析功能,几行代码即可搞定大部分路网分析。然而,OSMnx版本更新大,网上的教程大多失效,遂成此篇。
关键词:OSMnx;路网数据获取与分析;
OSMnx是南加州大学城市数据实验室(Urban Data Lab)的主任Geoff Boeing开发的一款街区网络分析库。
Geoff Boeing的研究方向是利用计算数据科学和空间分析来探索世界各地的城市交通模式,因此他开发了这样一款非常强大的工具,并在论文中广泛使用。
图1 图底分析 [1]
图2 死胡同分析 [1]
图3 最短路径分析 [1]
图4 与QGIS和AI的联动
OSMnx以OpenStreetMap为数据源,可以轻松的下载POI、建筑、高程数据。你可以利用极少的代码实现城市网络建模、分析和可视化。主体功能如下:
一行代码下载和可视化全世界的街道网络、建筑、高程、POI 进行拓扑和空间分析,自动计算几十个指标 最短路径分析(距离、时间、海拔最小化) 绘制等时圈(根据出行距离、时间) 绘制街道网络和建筑物平面图
最后,你可以将分析结果导出shp,GraphML或SVG文件。shp可以导入ESRI ArcGIS进行后续分析,GraphML可以和Gephi、networkx等软件联动,进一步对路网进行网络分析(当然通过OSMnx也可以完成网络分析)。SVG可以导入AI编辑。
最值得称道的是,在OSMnx底层简化和更正了OSM路网的网络拓扑,以清理节点和合并交叉点。如下图所示,左上角是OSM的路网数据,它们包括交叉口,但也包括沿着街道曲线的单个街道段的点。后者不是图论意义上的节点,因此OSMnx通过算法去除它们,最终得到右下角的干净的拓扑结构。
图5 拓扑优化过程
使用OSMnx的另一个优势在于,可以很方便的导出shp文件,而在OpenStreetMap上下载的osm文件,则需要通过ArcGIS Editor for OSM插件(下载地址:https://github.com/Esri/arcgis-osm-editor )进行较为复杂的操作才能使用。
接下来具体介绍OSMnx的具体使用方法和代码。注意:由于网络原因,部分功能需翻墙。
一、 OSM数据抓取
OSMnx图形模块对输入信息进行地理编码,从Nominatim API检索该城市的地点边界,从Overpass API检索这些边界内的可行驶街道网络数据,构建图形模型,然后简化/修正其拓扑结构,使节点表示交叉点和死角,边表示连接它们的街道段。
import osmnx as ox
G = ox.graph_from_address(address="天津大学, 天津市, 中国", dist=1000, dist_type="bbox",network_type='drive')
ox.plot_graph(G)
图6 OSMnx与OSM可视化对比
通过上述三行代码,我们得到了天津大学的路网数据,右侧是我利用ArcGIS得到的可视化结果。对比二者可以发现,OSMnx的路网拓扑关系非常完美,而OSM的节点非常多。OSMnx和ArcGIS生成的均是WGS84地理坐标系。在时间上,三行代码只用了10秒钟,而ArcGIS操作了5分钟。
解释下ox.graph_from_address这个API,它的功能是根据地址和距离抓取OSM数据。address中要输入待查询地址,与在OSM中直接搜索的关键词一致。dist指返回图形中心1000m范围内的节点。dist_type可选network和bbox,前者指保留那些与最中心的节点有一定网络距离的节点,后者指保留在距离边界框内的节点。network_type可选“ all_private”, "all" 所有, "bike" 自行车, "drive" 开车, "drive_service" 开车服务, "walk"步行几类路网信息。另外一个值得一提的参数是clean_periphery,如果为真,建立500米缓冲区以获得比请求更大的图形,然后简化,然后截断空间边界外的多余部分。
解释下ox.plot_graph这个API,它负责绘制空间几何图形,街道网络和路径。它的几个参数:G为待输入graph;figsize为图片大小,可输入(长, 宽)元组;bgcolor、node_color、node_alpha、edge_color等等是用来调节背景、节点、边缘的颜色、透明度等可视化效果。save和filepath用来保存图片。
除了用地址查询,OSMnx还提供了多样的查询方式。
osmnx.graph.graph_from_bbox(north=51.5052, south=51.5029, east=122.3997, west=122.4023) # 根据边框经纬度抓取OSM
osmnx.graph.graph_from_point(center_point=(51.5052, 122.3997), dist=1000 1000) # 根据中心点经纬度和亲抓取OSM
osmnx.graph.graph_from_place(quary="Piedmont, California, USA") # 根据可查询的多边形边界抓取OSM
二、 数据类型转换
数据类型转换的API如下:
# 将有向图转换为无向图
M = ox.get_undirected(G)
# 将有向图转换无平行边的有向图
M = ox.get_digraph(G)
# 将图形转换为节点和边的GeoDataFrames类型
gdf_nodes, gdf_edges = ox.graph_to_gdfs(G)
# 将节点和边的GeoDataFrames类型转换为图形
G = ox.graph_to_gdfs(gdf_nodes, gdf_edges)
图7 节点与边信息
三、 osmnx.basic_stats 统计模块
这个模块用来计算图的基本描述性几何和拓扑度量。r如果想要输出密度指标,需要传入面积。如果想要输出清洁节点,则需要传入清洁阈值。所谓清洁节点就是连接到该节点的其他节点数大于阈值,即为清洁节点。
G_proj = ox.project_graph(G)
nodes_proj = ox.graph_to_gdfs(G_proj, edges=False)
graph_area_m = nodes_proj.unary_union.convex_hull.area
ox.basic_stats(G_proj, area=graph_area_m, clean_int_tol=15)
图8 数据统计结果
解释一下上述代码。第一行代码负责作标系转换,如果不输入作标系,则默认以图中心点的UTM区为作标系。如果不重新计算坐标系,则空间属性会计算错误。第二行代码将原始数据类型转换为GeoPandas库的GeoDateFrame类型,然后用unary_union和convex_hull函数获取布尔联合后的凸壳的面积,这一步属于GeoPandas操作。最后将面积导入统计模块,即可得到上图中的统计结果。包括节点数、边数、平均节点度、街道总长度、街道平均长度、街道平均节点数、节点数分布和数量、交叉点个数、每平方公里的节点密度、交叉口密度、边密度和街区密度等。
四、 osmnx.save_graph_shapefile 储存模块
直接用osmnx.save_graph_shapefile模块就可以将路网数据保存为shp格式了。
ox.save_graph_shapefile(G, filepath=r".\mynetwork.shp")
五、 接近中心性分析
首先利用networkx.line_graph()将图转换为线图,即将边视为节点。然后利用networkx中的接近中心性分析模块,计算出每条边的接近中心性。最后将值映射到地图上。
注释:接近中心性(Closeness Centrality)反映在网络中某一节点与其他节点之间的接近程度。将一个节点到所有其他节点的最短路径距离的累加起来的倒数表示接近性中心性。
edge_centrality = nx.closeness_centrality(nx.line_graph(G))
nx.set_edge_attributes(G, edge_centrality, "edge_centrality")
ec = ox.plot.get_edge_colors_by_attr(G, "edge_centrality", cmap="inferno")
fig, ax = ox.plot_graph(G, edge_color=ec, edge_linewidth=2, node_size=0)
图9 接近中心性分析
六、 最短路径分析
根据经纬度坐标提供起始点和终止点,设定不同道路类型的速度值,便可以得到最短路径。同时可以输出最短路径的长度,以及起始点和终止点的直线距离。
orig = ox.distance.nearest_nodes(G, X=117.153, Y=39.107)
dest = ox.distance.nearest_nodes(G, X=-117.169, Y=39.113)
speeds = { 'motorway' : 80,
'trunk' : 80,
'primary' : 70,
'secondary' : 50,
'motorway_link' : 50,
'trunk_link' : 50,
'primary_link' : 50,
'secondary_link' : 50,
'residential': 35,
'tertiary': 60
}
G = ox.speed.add_edge_speeds(G,hwy_speeds=speeds,fallback=50)
G = ox.speed.add_edge_travel_times(G)
route = ox.shortest_path(G, orig, dest, weight="travel_time")
edge_lengths = ox.utils_graph.get_route_edge_attributes(G, route, "length")
sum_length = round(sum(edge_lengths))
orig_x = G.nodes[orig]["x"]
orig_y = G.nodes[orig]["y"]
dest_x = G.nodes[dest]["x"]
dest_y = G.nodes[dest]["y"]
direct_length = round(ox.distance.great_circle_vec(orig_y, orig_x, dest_y, dest_x))
fig, ax = ox.plot_graph_route(G, route, node_size=0)
图10 最短路径分析
以上就是OSMnx的具体用法,更为详细的使用方法请参考下文提供的链接。
类别 | 网址 |
官网 | https://geoffboeing.com/2016/11/osmnx-python-street-networks/ |
GitHub | https://github.com/gboeing/osmnx |
说明文档 | https://osmnx.readthedocs.io/en/stable/ osmnx.html#module-osmnx.stats |
案例文件 | https://github.com/gboeing/osmnx-examples |
论文 | https://geoffboeing.com/publications/osmnx-complex-street-networks/ |
参考文献
Boeing, G. OSMnx: New Methods for Acquiring, Constructing, Analyzing, and Visualizing Complex Street Networks. Computers, Environment and Urban Systems.2017,65:126-139. doi:10.1016/j.compenvurbsys.2017.05.004
编辑 / 肖天意
校对 / 张舒